package com.benchproject.patterns.state;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class StateMachine {

	private State loggedInState;
	private State loggedOutState;
	private State disabledState;

	private State currentState;

	private List<String> history;

	private Map<String, State> allStates;

	private int historyIndex = 1;

	public StateMachine() {

		loggedInState = new LoggedInState();
		loggedOutState = new LoggedOutState();
		disabledState = new DisabledState();
		history = new ArrayList<String>();
		allStates = new HashMap<String, State>();

		currentState = loggedOutState;
		history.add(loggedOutState.getClass().getName());

		allStates.put(LoggedInState.class.getName(), loggedInState);
		allStates.put(LoggedOutState.class.getName(), loggedOutState);
		allStates.put(DisabledState.class.getName(), disabledState);
	}

	public ActionForwardUrl handleEvent(Events event) {

		ActionForwardUrl forward = null;

		switch (event) {

		case USER_SUPPLIES_CORRECT_CREDENTIALS:
			forward = loggedInState.doSomethingAndReturnForward();
			setCurrentState(loggedInState);
			break;
		case USER_SUPPLIES_INCORRECT_CREDENTIALS:
			forward = loggedOutState.doSomethingAndReturnForward();
			setCurrentState(loggedOutState);
			break;
		case USER_LOGS_OUT:
			forward = loggedOutState.doSomethingAndReturnForward();
			setCurrentState(loggedOutState);
			break;
		case USER_FAILS_LOGIN_TWICE:
			forward = disabledState.doSomethingAndReturnForward();
			setCurrentState(disabledState);
			break;
		}

		return forward;
	}

	public ActionForwardUrl handleBack() {
		if (historyIndex < this.history.size()) {
			String previousStateName = this.history.get((this.history.size() - 1) - historyIndex);
			State previousState = allStates.get(previousStateName);
			this.currentState = previousState;
		}
		return this.currentState.doSomethingAndReturnForward();
	}

	public ActionForwardUrl handleForward() {
		if (historyIndex < this.history.size()) {
			String nextStateName = this.history.get(historyIndex + 1);
			State nextState = allStates.get(nextStateName);
			this.currentState = nextState;
		}
		return this.currentState.doSomethingAndReturnForward();
	}

	public State getCurrentState() {
		return this.currentState;
	}

	private void setCurrentState(State state) {
		this.currentState = state;
		this.history.add(state.getClass().getName());
	}

}
